﻿using DotNetty.Handlers.Logging;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels.Sockets;
using DotNetty.Transport.Channels;
using DotNetty.Handlers.Timeout;
using DotNetty.Codecs;
using System.Text;

namespace IdleTestServer
{
    internal class Program
    {
        static async Task RunServerAsync()
        {
            // bossGroup线程专门来处理客户端的连接
            var bossGroup = new MultithreadEventLoopGroup();
            // workGroup线程处理收发数据的交互
            var workGroup = new MultithreadEventLoopGroup();

            try
            {
                // bootstrap:管理ServerSocket的生命周期
                ServerBootstrap bootstrap = new ServerBootstrap();
                bootstrap.Group(bossGroup, workGroup)
                .Channel<TcpServerSocketChannel>() // 使用TCP协议的socket通信
                 // so_backlog 临时存放已完成三次握手的请求队列的最大长度，如果频繁连接可以调大此参数
                .Option(ChannelOption.SoBacklog, 1024) // 设置全连接队列大小
                // Option设置底层参数,这里设置基于TCP的socket它是没有延迟的
                .ChildOption(ChannelOption.TcpNodelay, true)// // nagle 算法开关，实时性要求高就关闭  
                .Handler(new LoggingHandler(LogLevel.DEBUG))// 添加dotnetty自带的日志处理器
                .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>  // 处理管道的处理器
                {
                    var pipeline = channel.Pipeline;

                    pipeline.AddLast(new StringDecoder(Encoding.UTF8), new StringEncoder(Encoding.UTF8));

                    // 添加心跳机制的处理器
                    // 参数1:读空闲(秒数),参数2:写空闲(秒速),参数3:读写空闲(秒速)
                    // 读空闲指:服务器监听在几秒内没有收到(读操作)数据,那么认为客户端是处在一个空闲的状态,从而触发UserEventTriggered事件.写空闲和读写空闲同理.
                    pipeline.AddLast(new IdleStateHandler(5, 5, 8));

                    pipeline.AddLast(new IdleTestServerHandler());
                }));

                int port = 8888;
                // 不指定ip,默认是127.0.0.1/localhost/局域网地址如:192.168.2.89
                var bootstrapChannel = await bootstrap.BindAsync(port);
                Console.WriteLine($"服务器已启动port:{port}");
                Console.ReadKey();

                // 关闭通信的Channel
                await bootstrapChannel.CloseAsync();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                // dotnetty优雅关闭的机制
                // Task.WaitAll():等待所有任务都处理完之后执行
                Task.WaitAll(bossGroup.ShutdownGracefullyAsync(), workGroup.ShutdownGracefullyAsync());
            }

        }

        static async Task Main(string[] args) => await RunServerAsync();
    }
}